<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body>*:not(.aside) {
            width: 500px;
            height: 500px;
            background-color: pink;
            margin: 0 auto;
            margin-bottom: 50px;
        }

        .aside {
            /* 默认隐藏 */
            display: none;
            position: fixed;
            left: 50%;
            top: 50px;
            margin-left: -260px;
            transform: translateX(-100%);
            list-style: none;
            width: 100px;
            height: 100px;
            line-height: 33.33px;
            text-indent: 10px;
            background-color: skyblue;
        }

        /* 当前状态 */
        .aside .current {
            background-color: pink;
        }
    </style>

    <script>
        document.addEventListener('DOMContentLoaded', function () {
            // 获取元素
            let top = document.querySelector('.top');
            let aside = document.querySelector('.aside');
            let step = document.querySelectorAll('.step');
            let flag = true;

            // 点击滚动到指定位置
            aside.querySelectorAll('li').forEach((el, i) => el.setAttribute('data-index', i));
            aside.addEventListener('click', function (e) {
                if (e.target.nodeName == 'LI') {
                    flag = false;
                    let index = e.target.getAttribute('data-index');
                    let timer = setInterval(function () {
                        let topY = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
                        let target = step[index].offsetTop;
                        let n = (target - topY) / 10;
                        n = n > 0 ? Math.ceil(n) : Math.floor(n);
                        if (Math.abs(topY - target) < 10) {
                            clearInterval(timer);
                            flag = true;
                        }
                        window.scrollTo(0, topY + n);
                    }, 15);
                    aside.querySelector('.current').className = '';
                    e.target.className = 'current';
                }
            });

            // 滚动到 top 模块
            window.addEventListener('scroll', function () {
                let topY = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
                if (topY > top.offsetTop) {
                    aside.style.display = 'block';
                } else {
                    aside.style.display = 'none';
                }

                // 滚动改变固定栏着色
                if (flag) {
                    step.forEach((el, i) => {
                        if (topY >= el.offsetTop) {
                            aside.querySelector('.current').className = '';
                            aside.children[i].className = 'current';
                        }
                    });
                }
            });
        });
    </script>
</head>

<body>
    <header>header</header>
    <section class="top step">top</section>
    <section class="middle step">middle</section>
    <section class="bottom step">bottom</section>
    <footer>footer</footer>
    <!-- 电梯导航 -->
    <ul class="aside">
        <li class="current">top</li>
        <li>middle</li>
        <li>bottom</li>
    </ul>
</body>

</html>